package cn.ihna.demo.algorithm.rbtree;

import java.util.LinkedList;

/**
 * 给晓瑶直播写的 哈哈哈
 *
 * @author xianyingda@gmail.com
 * @serial
 * @since 2020-08-29 20:46
 */
public class RBT<K extends Comparable<K>, V> {

    public static final boolean RED = true;
    public static final boolean BLACK = false;

    public static int count = 0;

    private int size;
    private Node root;

    public int size() {
        return this.size;
    }

    public void printMid() {
        printMid(root);

    }
    private void printMid(Node node) {
        if (node == null) {
            return;
        }
        printMid(node.left);
        System.out.println(node.key);
        printMid(node.right);
    }

    public void print() {
        LinkedList<Node> list = new LinkedList<>();
        list.addLast(root);
        print0(list);
        System.out.println("count = " + count);
    }

    public void print0(LinkedList<Node> list) {
        if (list == null || list.size() == 0) {
            return;
        }
        Node node;
        LinkedList<Node> next = new LinkedList<>();
        while ((node = list.pollFirst()) != null) {
            if (isRed(node)) {
                count++;
            }
            System.out.print(node.key + "(" + (isRed(node) ? "r" : "b") + ") ");
            if (node.left != null) {
                next.addLast(node.left);
            }
            if (node.right != null) {
                next.addLast(node.right);
            }
        }
        System.out.println();
        print0(next);
    }

    public static void main(String[] args) {
        RBT<Integer, Integer> rbt = new RBT<>();
        for (int i = 0; i < 100000; i++) {
            rbt.add(i, i + 100);
        }
        rbt.printMid();
    }

    public void add(K key, V value) {
        root = add(root, key, value);
        root.color = BLACK;
    }

    private Node add(Node node, K key, V value) {
        if (node == null) {
            size++;
            return new Node(key, value);
        }

        if (key.compareTo(node.key) < 0) {
            node.left = add(node.left, key, value);
        } else {
            node.right = add(node.right, key, value);
        }

        if (isRed(node.right) && !isRed(node.left)) {
            node = leftRotate(node);
            System.out.println("左旋了");
        }

        if (isRed(node.left) && isRed(node.left.left)) {
            node = rightRotate(node);
            System.out.println("右旋了");
        }

        if (isRed(node.left) && isRed(node.right)) {
            flipColors(node);
            System.out.println("我翻转了");
        }

        return node;
    }


    private class Node {
        boolean color;
        Node left, right;
        K key;
        V value;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.color = RED;
        }
    }


    private Node leftRotate(Node node) {
        Node x = node.right;
        node.right = x.left;
        x.left = node;
        x.color = node.color;
        node.color = RED;
        return x;
    }

    private Node rightRotate(Node node) {
        Node x = node.left;
        node.left = x.right;
        x.right = node;
        x.color = node.color;
        node.color = RED;
        return x;
    }


    private void flipColors(Node node) {
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }

    private boolean isRed(Node node) {
        if (node == null) {
            return BLACK;
        }
        return node.color;
    }


}
